﻿using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace RegexSharp.Core
{
    public class RegexEngine
    {
        private int _displayedCharsOfEachNode = 100;

        public RegexEngine()
        { }

        private string SubString(string str)
        {
            if (str.Length > _displayedCharsOfEachNode)
            {
                return str.Substring(0, _displayedCharsOfEachNode) + " ...";
            }
            else
            {
                return str;
            }
        }

        private string NodeString(int displayedIndex, string nodeContent)
        {
            return string.Format("[{0}]: {1}", displayedIndex, SubString(nodeContent));
        }

        private string NodeString(int displayedIndex, string groupName, string nodeContent)
        {
            return string.Format("[{0}]({1}): {2}", displayedIndex, groupName, SubString(nodeContent));
        }

        // Public Methods

        public TreeNode[] Matches(string content, Regex regex)
        {
            MatchCollection matches = regex.Matches(content);
            List<TreeNode> nodesOfMatches = new List<TreeNode>(matches.Count);

            for (int i = 0; i < matches.Count; i++)
            {
                TreeNode node = new TreeNode(NodeString(i, matches[i].Value));
                node.Tag = new HighlightInfo()
                {
                    Index = matches[i].Index,
                    Length = matches[i].Length
                };

                // start from 1, because 0 is match itself
                for (int j = 1; j < matches[i].Groups.Count; j++)
                {
                    TreeNode childNode = new TreeNode(NodeString(j, regex.GroupNameFromNumber(j), matches[i].Groups[j].Value));
                    childNode.Tag = new HighlightInfo()
                    {
                        Index = matches[i].Groups[j].Index,
                        Length = matches[i].Groups[j].Length
                    };

                    for (int k = 0; k < matches[i].Groups[j].Captures.Count; k++)
                    {
                        TreeNode childchildNode = new TreeNode(NodeString(k, matches[i].Groups[j].Captures[k].Value));
                        childchildNode.Tag = new HighlightInfo()
                        {
                            Index = matches[i].Groups[j].Captures[k].Index,
                            Length = matches[i].Groups[j].Captures[k].Length
                        };

                        childNode.Nodes.Add(childchildNode);
                    }

                    node.Nodes.Add(childNode);
                }

                nodesOfMatches.Add(node);
            }

            return nodesOfMatches.ToArray();
        }

        public string Replace(string content, Regex regex, string replacement)
        {
            return regex.Replace(content, replacement);
        }

        public string Replace(string content, Regex regex, MatchEvaluator matchEvaluator)
        {
            return regex.Replace(content, matchEvaluator);
        }

        public TreeNode[] Split(string content, Regex regex)
        {
            string[] results = regex.Split(content);
            List<TreeNode> nodesOfSplit = new List<TreeNode>(results.Count());

            for (int i = 0; i < results.Length; i++)
            {
                TreeNode childNode = new TreeNode(string.Format("[{0}]: {1}", i, results[i]));
                nodesOfSplit.Add(childNode);
            }

            return nodesOfSplit.ToArray();
        }
    }
}
